package com.ecarx.vhaltests.hy11.testcases.system.light;

import static android.car.VehiclePropertyIds.READING_LIGHTS_SWITCH;
import static com.ecarx.xui.adaptapi.car.base.ICarFunction.COMMON_VALUE_OFF;
import static com.ecarx.xui.adaptapi.car.base.ICarFunction.COMMON_VALUE_ON;

import android.car.VehicleAreaSeat;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.CarPropertyManager;

import com.ecarx.vhaltests.CallbackTimer;
import com.ecarx.vhaltests.IpcpClient;
import com.ecarx.vhaltests.VehicleConstants;
import com.ecarx.vhaltests.VhalUnitTestBase;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ReadingLightsSwitchTest extends VhalUnitTestBase {
    private static final int propertyId = READING_LIGHTS_SWITCH;
    private CallbackTimer cbkTimer = new CallbackTimer();
    private CarPropertyManager.CarPropertyEventCallback propertyCbk;
    private static IpcpClient ipcpClient = new IpcpClient();
    private boolean isFirstCbk;
    private static final int AREA_MAIN = VehicleAreaSeat.SEAT_ROW_1_LEFT
            | VehicleAreaSeat.SEAT_ROW_1_RIGHT
            | VehicleAreaSeat.SEAT_ROW_2_LEFT
            | VehicleAreaSeat.SEAT_ROW_2_RIGHT;
    private static final int AREA_ROW_1_L = VehicleAreaSeat.SEAT_ROW_1_LEFT;
    private static final int AREA_ROW_1_R = VehicleAreaSeat.SEAT_ROW_1_RIGHT;
    private static final int AREA_ROW_2_L = VehicleAreaSeat.SEAT_ROW_2_LEFT;
    private static final int AREA_ROW_2_R = VehicleAreaSeat.SEAT_ROW_2_RIGHT;

    @BeforeClass
    public static void testInit() {
        setAvailable(true);
        Assert.assertTrue(isAvail(AREA_MAIN));
        Assert.assertTrue(isAvail(AREA_ROW_1_L));
        Assert.assertTrue(isAvail(AREA_ROW_1_R));
        Assert.assertTrue(isAvail(AREA_ROW_2_L));
        Assert.assertTrue(isAvail(AREA_ROW_2_R));
    }

    @Test
    public void test001_ReadingLightsSwitchOn() {
        testSetGet(AREA_MAIN, COMMON_VALUE_ON);
        testSetGet(AREA_ROW_1_L, COMMON_VALUE_ON);
        testSetGet(AREA_ROW_1_R, COMMON_VALUE_ON);
        testSetGet(AREA_ROW_2_L, COMMON_VALUE_ON);
        testSetGet(AREA_ROW_2_R, COMMON_VALUE_ON);
    }

    @Test
    public void test002_ReadingLightsSwitchOff() {
        testSetGet(AREA_MAIN, COMMON_VALUE_OFF);
        testSetGet(AREA_ROW_1_L, COMMON_VALUE_OFF);
        testSetGet(AREA_ROW_1_R, COMMON_VALUE_OFF);
        testSetGet(AREA_ROW_2_L, COMMON_VALUE_OFF);
        testSetGet(AREA_ROW_2_R, COMMON_VALUE_OFF);
    }

    @Test
    public void test003_ReadingLightsSwitchCbk() {
        testCbk(AREA_MAIN);
        testCbk(AREA_ROW_1_L);
        testCbk(AREA_ROW_1_R);
        testCbk(AREA_ROW_2_L);
        testCbk(AREA_ROW_2_R);
    }

    @Test
    public void test004_ReadingLightsSwitchUnAvail() {
        setAvailable(false);
        Assert.assertFalse(isAvail(AREA_MAIN));
        Assert.assertFalse(isAvail(AREA_ROW_1_L));
        Assert.assertFalse(isAvail(AREA_ROW_1_R));
        Assert.assertFalse(isAvail(AREA_ROW_2_L));
        Assert.assertFalse(isAvail(AREA_ROW_2_R));
    }

    private static void setAvailable(boolean isAvail) {
        int ccSvcId = 135;
        int[] ccOperIds = {200};

        int cemSvcId = 37;
        int[] cemOperIds = {999};

        ipcpClient.setConfig(ccSvcId, ccOperIds);
        ipcpClient.setConfig(cemSvcId, cemOperIds);

        int[] ccConfigs = {526};
        int[] ccValues = {5};
        boolean ccRet = ipcpClient.setCarconfigSignal(ccSvcId, ccOperIds[0], ccConfigs, ccValues);
        Assert.assertTrue(ccRet);

        String[] cems = {"vehModMngtGlbSafe1CarModSts1", "vehModMngtGlbSafe1UsgModSts"};
        int[] cemValues = {isAvail ? VehicleConstants.CAR_MODE_NOMAL : VehicleConstants.CAR_MODE_TRANSPORT, VehicleConstants.USG_MODE_CONVENIENCE};
        boolean cemRet = ipcpClient.setCEMSignal(cemSvcId, cemOperIds[0], cems, cemValues);
        Assert.assertTrue(cemRet);
    }

    private void testSetGet(int areaId, int value) {
        setValue(areaId, value);
        delay();
        Assert.assertEquals(value, getValue(areaId));
    }

    private void setValue(int areaId, int value) {
        setAvailable(true);
        delay();
        mCarPropertyMgr.setIntProperty(propertyId, areaId, value);
    }

    private int getValue(int areaId) {
        delay();
        return mCarPropertyMgr.getIntProperty(propertyId, areaId);
    }

    private static boolean isAvail(int areaId) {
        delay();
        return mCarPropertyMgr.isPropertyAvailable(propertyId, areaId);
    }

    private void testCbk(int areaId) {
        isFirstCbk = true;
        setValue(areaId, COMMON_VALUE_OFF);
        delay();
        int expectedValue = COMMON_VALUE_ON;
        propertyCbk = new CarPropertyManager.CarPropertyEventCallback() {
            @Override
            public void onChangeEvent(CarPropertyValue carPropertyValue) {
                if (carPropertyValue.getAreaId() == areaId) {
                    if (isFirstCbk) {
                        isFirstCbk = false;
                    } else {
                        int value = (int) carPropertyValue.getValue();
                        Assert.assertEquals(expectedValue, value);
                        mCarPropertyMgr.unregisterCallback(propertyCbk);
                        delay();
                        cbkTimer.finish();
                    }
                }
            }

            @Override
            public void onErrorEvent(int i, int i1) {
            }
        };
        mCarPropertyMgr.registerCallback(propertyCbk, propertyId, CarPropertyManager.SENSOR_RATE_ONCHANGE);
        setValue(areaId, expectedValue);
        cbkTimer.start();
    }

}